package q1.project.modules.system.tenant.filter;

import jakarta.persistence.EntityManager;
import java.util.function.Supplier;
import org.hibernate.Filter;
import org.hibernate.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import q1.project.common.context.TenantContext;

/**
 * 租户过滤器管理器 负责启用和管理 Hibernate Filter，实现自动租户数据隔离
 *
 * <h3>使用场景：</h3>
 *
 * <ul>
 *   <li>普通请求：由 TenantFilterInterceptor 自动启用，无需手动处理
 *   <li>超级管理员查询：使用 executeWithoutTenantFilter() 临时禁用过滤器
 *   <li>跨租户操作：使用 executeWithTenant() 指定租户执行操作
 *   <li>定时任务：手动启用/禁用过滤器
 * </ul>
 *
 * @author Q1 Team
 * @version 1.0
 */
@Component
public class TenantFilterManager {

  private static final Logger log = LoggerFactory.getLogger(TenantFilterManager.class);
  private static final String TENANT_FILTER_NAME = "tenantFilter";
  private static final String SOFT_DELETE_FILTER_NAME = "softDeleteFilter";

  private final EntityManager entityManager;

  public TenantFilterManager(EntityManager entityManager) {
    this.entityManager = entityManager;
  }

  /**
   * 启用租户过滤器 应在每个请求开始时调用
   *
   * @return 是否成功启用
   */
  public boolean enableTenantFilter() {
    String tenantId = TenantContext.getTenantId();

    if (tenantId == null || tenantId.trim().isEmpty()) {
      log.debug("租户ID为空，不启用租户过滤器");
      return false;
    }

    try {
      Session session = entityManager.unwrap(Session.class);

      // 如果过滤器已启用，先禁用再重新启用（更新参数）
      Filter existingFilter = session.getEnabledFilter(TENANT_FILTER_NAME);
      if (existingFilter != null) {
        session.disableFilter(TENANT_FILTER_NAME);
      }

      Filter filter = session.enableFilter(TENANT_FILTER_NAME);
      filter.setParameter("tenantId", tenantId);

      log.debug("✅ 租户过滤器已启用: tenantId={}", tenantId);
      return true;
    } catch (Exception e) {
      log.error("启用租户过滤器失败: tenantId={}", tenantId, e);
      return false;
    }
  }

  /**
   * 启用软删除过滤器 默认只查询未删除的数据（deleted = false）
   *
   * @return 是否成功启用
   */
  public boolean enableSoftDeleteFilter() {
    try {
      Session session = entityManager.unwrap(Session.class);

      // 如果过滤器已启用，先禁用再重新启用
      Filter existingFilter = session.getEnabledFilter(SOFT_DELETE_FILTER_NAME);
      if (existingFilter != null) {
        session.disableFilter(SOFT_DELETE_FILTER_NAME);
      }

      Filter filter = session.enableFilter(SOFT_DELETE_FILTER_NAME);
      filter.setParameter("deleted", false);

      log.debug("✅ 软删除过滤器已启用: deleted=false");
      return true;
    } catch (Exception e) {
      log.error("启用软删除过滤器失败", e);
      return false;
    }
  }

  /** 禁用租户过滤器 应在特殊场景下使用（如超级管理员查询所有租户数据） */
  public void disableTenantFilter() {
    try {
      Session session = entityManager.unwrap(Session.class);
      Filter filter = session.getEnabledFilter(TENANT_FILTER_NAME);
      if (filter != null) {
        session.disableFilter(TENANT_FILTER_NAME);
        log.debug("租户过滤器已禁用");
      }
    } catch (Exception e) {
      log.warn("禁用租户过滤器失败", e);
    }
  }

  /** 禁用软删除过滤器 用于查询包括已删除的数据 */
  public void disableSoftDeleteFilter() {
    try {
      Session session = entityManager.unwrap(Session.class);
      Filter filter = session.getEnabledFilter(SOFT_DELETE_FILTER_NAME);
      if (filter != null) {
        session.disableFilter(SOFT_DELETE_FILTER_NAME);
        log.debug("软删除过滤器已禁用");
      }
    } catch (Exception e) {
      log.warn("禁用软删除过滤器失败", e);
    }
  }

  /**
   * 检查租户过滤器是否已启用
   *
   * @return true-已启用，false-未启用
   */
  public boolean isTenantFilterEnabled() {
    try {
      Session session = entityManager.unwrap(Session.class);
      return session.getEnabledFilter(TENANT_FILTER_NAME) != null;
    } catch (Exception e) {
      log.warn("检查租户过滤器状态失败", e);
      return false;
    }
  }

  /**
   * 临时禁用租户过滤器执行操作 用于超级管理员查询所有租户的数据
   *
   * <p>示例：
   *
   * <pre>
   * List&lt;User&gt; allUsers = tenantFilterManager.executeWithoutTenantFilter(() -&gt; {
   *     return userDao.findAll(); // 查询所有租户的用户
   * });
   * </pre>
   *
   * @param action 要执行的操作
   * @param <T> 返回类型
   * @return 操作结果
   */
  public <T> T executeWithoutTenantFilter(Supplier<T> action) {
    boolean wasEnabled = isTenantFilterEnabled();
    try {
      if (wasEnabled) {
        disableTenantFilter();
      }
      return action.get();
    } finally {
      if (wasEnabled) {
        enableTenantFilter();
      }
    }
  }

  /**
   * 使用指定租户ID执行操作 用于跨租户操作或定时任务
   *
   * <p>示例：
   *
   * <pre>
   * tenantFilterManager.executeWithTenant("tenant001", () -&gt; {
   *     return postService.processExpiredPosts(); // 处理特定租户的数据
   * });
   * </pre>
   *
   * @param tenantId 租户ID
   * @param action 要执行的操作
   * @param <T> 返回类型
   * @return 操作结果
   */
  public <T> T executeWithTenant(String tenantId, Supplier<T> action) {
    String originalTenantId = TenantContext.getTenantId();
    boolean wasEnabled = isTenantFilterEnabled();

    try {
      // 设置新的租户上下文
      TenantContext.setTenantId(tenantId);

      // 禁用旧的过滤器并启用新的
      if (wasEnabled) {
        disableTenantFilter();
      }
      enableTenantFilter();

      // 执行操作
      return action.get();

    } finally {
      // 恢复原始租户上下文
      if (originalTenantId != null && !originalTenantId.isEmpty()) {
        TenantContext.setTenantId(originalTenantId);
        disableTenantFilter();
        enableTenantFilter();
      } else {
        TenantContext.clear();
        disableTenantFilter();
      }
    }
  }

  /**
   * 执行不需要返回值的操作（使用指定租户）
   *
   * @param tenantId 租户ID
   * @param action 要执行的操作
   */
  public void executeWithTenant(String tenantId, Runnable action) {
    executeWithTenant(
        tenantId,
        () -> {
          action.run();
          return null;
        });
  }
}
